/**
 * Copyright (c) 2007,中企动力华南研发中心<br>
 * All rights reserved.
 */
package com.ce.pms.charge.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ce.pms.base.service.impl.PmsBaseServiceImpl;
import com.ce.pms.charge.dao.ICharStoChoGeneralDao;
import com.ce.pms.charge.dao.IChargeItemDao;
import com.ce.pms.charge.dao.IChargeStaDao;
import com.ce.pms.charge.dao.IPeriodLogDao;
import com.ce.pms.charge.model.AbstractStaVersion;
import com.ce.pms.charge.model.CharStaChoDomain;
import com.ce.pms.charge.model.ChargeStaDomain;
import com.ce.pms.charge.model.GeneralVersion;
import com.ce.pms.charge.service.ICharStoChoGeneralService;
import com.ce.pms.charge.vo.ChargeStaChoVO;
import com.ce.pms.common.model.SysrefcodeDO;
import com.ce.pms.exception.BusinessException;
import com.ce.pms.house.dao.IHouseDao;
import com.ce.pms.house.model.HouseDomain;
import com.ce.pms.house.service.IHouseService;
import com.sitechasia.webx.core.support.Page;

/**
 * 功能描述：房间标准选用常规费用服务类<br>
 * @author 罗军林 创建日期：2008-8-7
 */
public class CharStoChoGeneralServiceImpl extends PmsBaseServiceImpl implements
		ICharStoChoGeneralService {
	ICharStoChoGeneralDao charStoChoGeneralDao;
	IChargeItemDao chargeItemDao;
	IChargeStaDao chargeStaDao;
	IHouseService houseService;
	IHouseDao houseDao;
	IPeriodLogDao periodLogDao;



	/*
	 * (non-Javadoc)
	 * @see com.ce.pms.charge.service.ICharStoChoFixedService#queryCharStoChoFixed
	 * (com.ce.pms.charge.vo.ChargeStaChoConditionVO)
	 */
	public Page queryCharStoChoGeneral(ChargeStaChoVO condition) {
		Page page=charStoChoGeneralDao.queryCharStoCho(condition);

		page.setResult( convertDoToVoForList( page.getResult() ) );

		return page;
	}

	/*
	 * (non-Javadoc)
	 * @see com.ce.pms.charge.service.ICharStoChoFixedService#addCharStaChoFixed
	 * (com.ce.pms.charge.vo.CharStaChoFixedVO)
	 */
	public void addCharStaChoGeneral(ChargeStaChoVO charStaChoGeneralVO){

		checkParameterIsNull(charStaChoGeneralVO.getChargeStaID(), "charge:staid_not_null");
		checkParameterIsNull(charStaChoGeneralVO.getChargeItemID(), "charge:itemid_not_null");
		checkCreatorInfo(charStaChoGeneralVO.getCreater());

		Long stime=System.currentTimeMillis();
		AbstractStaVersion staVersion= chargeStaDao.queryCVersionByChargeStaId(charStaChoGeneralVO.getChargeStaID());
		Map<Long, BigDecimal> chargeAmts = getCalculateResultMap(charStaChoGeneralVO.getHouseIds(),staVersion);
		charStoChoGeneralDao.addCharStaCho(charStaChoGeneralVO, chargeAmts);
		logger.info("执行时间："+(System.currentTimeMillis()-stime));
		logger.info("计算结果："+chargeAmts.size());

	}

	/**
	 * 功能描述:更新指定收费标准的房间标准选用表中的费用,如果该标准还没有被选用将返回false<br>
	 * @param charStaId<br>
	 * @param staVersion
	 * Create author:罗军林<br>
	 * Create on:2008-10-10<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	public boolean updateCharstChoAmt(Long charStaId,AbstractStaVersion staVersion){
		checkParameterIsNull(charStaId, "charge:itemid_not_null");
		String houseIds=charStoChoGeneralDao.getHouseIdsByCharStaId(charStaId);
		if(null==houseIds || houseIds.trim().length()<=0){
			return false;
		}else{
			Map<Long, BigDecimal> chargeAmts = getCalculateResultMap(houseIds,staVersion);
			charStoChoGeneralDao.updateCharStoAmt(charStaId, chargeAmts);
			return true;
		}
	}

	/*
	 * (non-Javadoc)
	 * @see com.ce.pms.charge.service.ICharStoChoGeneralService#checkExistCharStoChoGeneral(com.ce.pms.charge.vo.ChargeStaChoVO)
	 */
	public Boolean checkExistCharStoChoGeneral(ChargeStaChoVO condition,ChargeStaChoVO oldCondition) {
		return charStoChoGeneralDao.checkExistCharStoChoGeneral(condition,oldCondition);
	}



	/*
	 * (non-Javadoc)
	 * @see com.ce.pms.charge.service.ICharStoChoGeneralService#deleteCharStaChoGeneral
	 * (java.lang.Long)
	 */
	public void deleteCharStaChoGeneral(Long keyword) {
		this.checkParameterIsNull(keyword, "charge:staChoid_not_null");

		CharStaChoDomain charStaChoDomain=charStoChoGeneralDao.findById(keyword);

		checkPeriodHasArcaculate(charStaChoDomain);

		charStoChoGeneralDao.deleteObjectById(keyword);
	}

	/*
	 * (non-Javadoc)
	 * @see com.ce.pms.charge.service.ICharStoChoGeneralService#editCharStaChoGeneral
	 * (com.ce.pms.charge.vo.CharStaChoGeneralVO)
	 */
	public ChargeStaChoVO editCharStaChoGeneral(ChargeStaChoVO charStaChoGeneralVO) {
		checkParameterIsNull(charStaChoGeneralVO.getChargeStaID(), "charge:staid_not_null");
		checkParameterIsNull(charStaChoGeneralVO.getChargeItemID(), "charge:itemid_not_null");

//		ChargeItemDomain chargeItemDomain=chargeItemDao.findById(charStaChoGeneralVO.getChargeItemID());
		CharStaChoDomain charStaChoDomain=charStoChoGeneralDao.findById(charStaChoGeneralVO.getKeyword());

		checkPeriodHasArcaculate(charStaChoDomain);

		ChargeStaDomain chargeStaDomain=chargeStaDao.findById(charStaChoGeneralVO.getChargeStaID());

		//重新计算费用
		BigDecimal amt= chargeStaDomain.getCVersion().calculate(getAmount(chargeStaDomain.getCVersion(), charStaChoDomain.getHouse()));
		charStaChoDomain.setChargeAmt(amt);
		charStaChoDomain.setChargeItem(chargeStaDomain.getChargeItem());
		charStaChoDomain.setChargeSta(chargeStaDomain);
		this.modifyInfo(charStaChoDomain.getSysInfo(), charStaChoGeneralVO.getCreater());

		return convertDoToVO(charStaChoDomain);
	}

	/**
	 * 功能描述:检查是否做过应收计算<br>
	 * @param charStaChoDomain<br>
	 * Create author:罗军林<br>
	 * Create on:2008-10-31<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void checkPeriodHasArcaculate(CharStaChoDomain charStaChoDomain) {
		if( periodLogDao.checkPeriodHasArcaculate(charStaChoDomain.getHouse().getBuilding().getKeyword()) ){
			throw new BusinessException("charge:peiord_has_calculate",BusinessException.ERROR);
		}
	}



	/* (non-Javadoc)
	 * @see com.ce.pms.charge.service.ICharStoChoGeneralService#findCharStoChoById(java.lang.Long)
	 */
	public ChargeStaChoVO findCharStoChoById(Long keyword) {
		this.checkParameterIsNull(keyword, "charge:staChoid_not_null");
		return convertDoToVO( charStoChoGeneralDao.findById(keyword) );
	}

	/** 功能描述:DO列表转VO列表<br>
	 * @param list<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-12<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private List<ChargeStaChoVO> convertDoToVoForList(List<CharStaChoDomain> list) {
		List<ChargeStaChoVO> result=new ArrayList<ChargeStaChoVO>();
		for(CharStaChoDomain charsta : list){
			ChargeStaChoVO charStaChoGeneralVO = convertDoToVO(charsta);
			result.add(charStaChoGeneralVO);
		}
		return result;
	}

	/** 功能描述:DO转VO（走表）<br>
	 * @param charsta
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-12<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private ChargeStaChoVO convertDoToVO(CharStaChoDomain charsta) {
		ChargeStaChoVO charStaChoGeneralVO = new ChargeStaChoVO();
		charStaChoGeneralVO.setKeyword(charsta.getKeyword());
		if( charsta.getHouse() != null){
			charStaChoGeneralVO.setHouseId(charsta.getHouse().getKeyword());
			charStaChoGeneralVO.setHouseNumber(charsta.getHouse().getHouseNumber());
			charStaChoGeneralVO.setOwnerName(houseService.getOwnerNameBy(charsta.getHouse().getHouseNumber()));
		}
		if( charsta.getChargeItem() != null){
			charStaChoGeneralVO.setChargeItemID(charsta.getChargeItem().getKeyword());
			charStaChoGeneralVO.setChargeItemName(charsta.getChargeItem().getItemName());
		}

		if(charsta.getChargeSta() != null){
			charStaChoGeneralVO.setChargeStaID(charsta.getChargeSta().getKeyword());
			charStaChoGeneralVO.setChargeStaName(charsta.getChargeSta().getStaName());
		}

		return charStaChoGeneralVO;
	}

	/**
	 * 功能描述:获得指定格式的时间字符串，如果参数有一个为空，将返回null<br>
	 * @param pattern
	 * @param date
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-14<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private String getDateString(String pattern,Date date){
		if(pattern==null || date==null){
			return null;
		}else{
			 SimpleDateFormat sf=new SimpleDateFormat(pattern);
			 return sf.format(date);
		}
	}
	/**
	 * 功能描述:检查房号列表是否符合指定格式，例1,2,3,4<br>
	 * @param charStaChoGeneralVO<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-13<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void checkHouseIdsFormat(ChargeStaChoVO charStaChoGeneralVO) {
		if( charStaChoGeneralVO.getHouseIds() == null ||
				!charStaChoGeneralVO.getHouseIds().matches("((\\d,)|(\\d))+?")){
			throw new BusinessException("charge:houseid_format_exception",BusinessException.WARNING);
		}
	}

	/**
	 * 功能描述:根据房号id列表，及所选用的收费标准分批计算并返回计算结果,key为房号，value为计算结果。<br>
	 * 注：如果其中某个房号不存在，将跳过，其结果不会存入map中<br>
	 * @param houseIds
	 * @param chargeStaId
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-18<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private Map<Long, BigDecimal> getCalculateResultMap(String houseIds,AbstractStaVersion staVersion) {
		Map<Long, BigDecimal> map = new HashMap<Long, BigDecimal>();
		String[] hids=houseIds.split(",");
		StringBuffer hidsStr=new StringBuffer();
		for(int i=0;i<hids.length;i++){
			hidsStr.append(hids[i]).append(",");
			if((i+1) % 100 == 0 || i==(hids.length-1) ){
				hidsStr.deleteCharAt(hidsStr.length()-1);
				calculate(hidsStr.toString(), staVersion, map);
				hidsStr.delete(0, hidsStr.length());
			}
		}
		return map;
	}

	/**
	 * 功能描述:调用计算规则进行计算并将结果放入到MAP中<br>
	 * @param charStaChoGeneralVO
	 * @param map<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-15<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private void calculate(String houseIds,AbstractStaVersion staVersion, Map<Long, BigDecimal> map) {
		List<HouseDomain> houseList=houseDao.getHouseListByIds(houseIds);
		//AbstractStaVersion staVersion= chargeStaDao.queryCVersionByChargeStaId(staId);
		for(HouseDomain house : houseList){
			BigDecimal result= staVersion.calculate(getAmount(staVersion,house));
			map.put(house.getKeyword(), result);
		}
	}

	/**
	 * 功能描述:根据计算规则，如果计算参数返回建筑面积或套内面积<br>
	 * @param staVersion
	 * @param amount
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-15<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal getAmount(AbstractStaVersion staVersion, HouseDomain houseDomain) {
		BigDecimal amount=null;
		if(staVersion instanceof AbstractStaVersion){
			if(SysrefcodeDO.FEE_CHARGESTA_CAST_VALUE_BUILDAREA.equals(((GeneralVersion)staVersion).getCountParameter())){
				amount=houseDomain.getBuildSize();
			}else if(SysrefcodeDO.FEE_CHARGESTA_CAST_VALUE_SETAREA.equals(((GeneralVersion)staVersion).getCountParameter())){
				amount=houseDomain.getInnerSize();
			}
		}
		return amount;
	}

	/***
	 * 功能描述:  查询指定房间的收费标准<br>
	 * @param houseId
	 * @return
	 * Create author:yandawei <br>
	 * Create on:2008-10-22  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public List<ChargeStaChoVO> getAllSelectHouseCharStoCho(Long houseId) {
		List<CharStaChoDomain> list = charStoChoGeneralDao.queryCharStaChoByHouseId(houseId);
		List<ChargeStaChoVO> result=new ArrayList<ChargeStaChoVO>();
		for(CharStaChoDomain charsta : list){
			boolean isMeter = charsta.getMeter() != null && SysrefcodeDO.CONSTANTS_DIGITAL_ONE.equals(charsta.getMeter().getValidity());
			boolean other = charsta.getMeter() == null;
			if(isMeter || other){
				ChargeStaChoVO charStaChoGeneralVO = convertDoToVO(charsta);
				result.add(charStaChoGeneralVO);
			}
		}
		return result;
	}



	/**********************************************************************************/
	public void setChargeItemDao(IChargeItemDao chargeItemDao) {
		this.chargeItemDao = chargeItemDao;
	}

	public void setChargeStaDao(IChargeStaDao chargeStaDao) {
		this.chargeStaDao = chargeStaDao;
	}

	public void setCharStoChoGeneralDao(ICharStoChoGeneralDao charStoChoGeneralDao) {
		this.charStoChoGeneralDao = charStoChoGeneralDao;
	}

	public void setHouseService(IHouseService houseService) {
		this.houseService = houseService;
	}

	public void setHouseDao(IHouseDao houseDao) {
		this.houseDao = houseDao;
	}

	public void setPeriodLogDao(IPeriodLogDao periodLogDao) {
		this.periodLogDao = periodLogDao;
	}



}
